import pandas as pd

from utils.log import MyLog
from utils.sql_handler import SqlHandler
from utils.redis_handler import RedisHandler
from utils.faiss_handler import BuitIndex
from utils.title_info import TitleInfo
from config import Config
from tqdm import tqdm
import os, psutil
import datetime
import json



class CorrelationCircle:
    def __init__(self, config):
        self.config = config
        self.log = MyLog(config.log_dir, __name__).getlog()
        self.info = TitleInfo(config)
        self.red = RedisHandler(config)
        self.index = BuitIndex(config)
        self.history = self.index.bulit()
        self.title2vec = self.index.title2vec
        self.history.rename(columns={'ctime':'ctime'},inplace=True)
        self.log.info(self.MemoryUsed())
        self.count = 1

    def MemoryUsed(self):
        # 查看当前进程使用的内存情况
        process = psutil.Process(os.getpid())
        info = 'Used Memory: %.3f MB' % (process.memory_info().rss / 1024 / 1024)
        return info

    def find(self, group_id):
        recall_circle = open('circle_recall.txt','a+',encoding='utf-8')
        with SqlHandler(self.config) as sql:
            result = []
            sample = sql.search_by_group_id(group_id)
            title, time, classes = sample.get('title'), int(sample.get('ctime').timestamp()), sample.get('category')
            info = self.info.titleinfo(title)
            titlevec = self.title2vec(title)
            sim_socre, sim_id = self.index.search(titlevec, 50)
            recall = [{key: self.history.loc[self.history['id'] == i][key].values[0] for key in sql.keys} for i in
                      sim_id[0]]
            for recall in recall:
                r_title, r_time, r_classes,r_goupid = recall.get('title'), recall.get('ctime'), recall.get('category'), recall.get('ext0')
                r_time = int(datetime.datetime.strptime(r_time, '%Y-%m-%d %H:%M:%S').timestamp())
                if time - r_time < 86400: continue
                r_info = self.info.titleinfo(r_title)
                if len(r_info.get('words')) <= 2 or len(r_title.split(' ')) == 2: continue
                score = self.Tversky(info.get('words'), r_info.get('words'))
                same = self.Tversky(list(title), list(r_title))
                if classes == r_classes: score *= 1.2
                if score >= 0.1 and same < 0.6:
                    # if not pd.isna(r_goupid):
                    #     sums_tiezi = self.red.count_tiezi(int(r_goupid))
                    #     self.log.info(f'{int(r_goupid)}:{sums_tiezi}')
                    #     if sums_tiezi < 20:
                    #         continue
                    res = {'title': r_title,
                           'group_id': recall.get('ext0'),
                           'ctime': r_time}
                    if [True for i in result if self.Tversky(list(r_title), list(i[0].get('title'))) >= 0.6]:
                        continue
                    sim = self.info.rule_limit(title,r_title,info,r_info)
                    self.log.info(f'{title}\t{r_title}\t{sim}')
                    if sim:
                        if classes != r_classes: sim *= 0.5
                        result.append((res, round(sim+5*same,2)))
        if not result: return
        result = sorted(result, key=lambda x: x[1], reverse=True)
        result = result[:5]

        self.count += 1
        recall_circle.write('-'*10+str(self.count)+'  '+title+'-'*10+'\n')
        for i in result:
            self.log.info(f"{self.count}\t{title}--{i[0].get('title')}------------{i[1]}")
            recall_circle.write(i[0].get('title') + '\n')
        recall_circle.write('\n')


    def Tversky(self, list_1, list_2):
        if not list_1 or not list_2: return 0.0
        inter = float(len(set(list_1).intersection(set(list_2))))  # 交集
        l1_except = float(len(set(list_1).difference(set(list_2))))  # 在l1不在l2
        l2_except = float(len(set(list_2).difference(set(list_1))))  # 在l2不在l1
        return inter / (inter + l1_except + l2_except) if inter else 0

    def get_correlation(self, group_id):
        with SqlHandler(self.config) as sql:
            title = sql.groupid_title(group_id)
            event_exits = self.red.title_exist(title)
            return event_exits

    def run(self):
        with SqlHandler(self.config) as sql:
            groupid_list = sql.search_current()
            # for id in tqdm(groupid_list):
            for id in tqdm(groupid_list):
                if id:
                    self.find(id[0])

    def search_groupid(self, groupid):
        self.find(groupid)

    def valid(self):
        with SqlHandler(self.config) as sql:
            h = f"select ext0 from sina_news_hot_search where ext0 != '' and ext1='1'order by ctime desc limit 2000"
            res = sql.large_search(h)
            data = res.drop_duplicates(keep='first')
            for i in tqdm(data.values):
                if i: self.find(i[0])
            self.log.info(self.MemoryUsed())
            print('-' * 50)
            # for i in tqdm(data.values):
            #     print(self.get_correlation(i[0]))

    def test(self):
        id_list = open('./data/groupid_list.txt','r',encoding='utf-8').readlines()
        for i in id_list:
            if i:
                self.find(i.strip())


if __name__ == '__main__':
    opt = Config()
    a = CorrelationCircle(opt)
    a.test()

